const eventKind = {
  EVENT_REMOVE_USER: 'remove_user',
  EVENT_PROJECT_REMOVE: 'remove_project',
  EVENT_VERSION_REMOVE: 'remove_version',
  EVENT_FILE_REMOVE: 'remove_file',
  EVENT_FILE_RESET: 'reset_file',
  EVENT_FUNCTION_REMOVE: 'remove_function',
  EVENT_FUNCTION_REMOVED: 'remove_function_after',
  EVENT_NEW_TASK: 'new_task',
  EVENT_TASK_QUEUE_REMOVED: 'task_queue_removed',
  EVENT_FUNCTION_RESET: 'reset_function',
};

class EventHub {
  constructor() {
    this.chain = new Map();
  }

  on(eventName, callback) {
    eventName = [].concat(eventName);
    eventName.forEach((eName) => {
      if (!this.chain.has(eName)) {
        this.chain.set(eName, []);
      }
      this.chain.get(eName).push(callback);
    });
  }

  async emit(eventName, ...args) {
    if (!this.chain.has(eventName)) {
      return Promise.resolve();
    }
    return Promise.all(this.chain.get(eventName).map((callback) => callback(...args)));
  }

  async emitSync(eventName, ...args) {
    if (!this.chain.has(eventName)) {
      return Promise.resolve();
    }
    let queue = Promise.resolve();
    this.chain.get(eventName).forEach((callback) => {
      queue = queue.then(() => callback(...args));
    });
    return queue;
  }

  removeListenersByEvent(eventName) {
    this.chain.delete(eventName);
  }

  removeAllListeners() {
    this.chain.clear();
  }
}

const eventHub = new EventHub();

module.exports = {
  eventHub,
  eventKind,
};
